/*
 * timer及中断处理示例
 */
/* C头文件，支持标准C库, 可以跨平台 */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>

#include <tests_lib.h>
#include <io.h>

/*
 * 中断处理,需引用此头文件
 */
#include <interrupts.h>
/*
 * 这个头文件定义了CPU相关的接口
 * 注意: arch/开头的头文件表示不是个跨平台的，
 *      仅在真实ARM环境可用，DPI-C环境无法用
 */
#include <cpu.h>

/* 本测例需要引用ARMv8 arch timer相关函数 */
#include <arch_timer.h>
/* 引用了delay函数 */
#include <delay.h>

static volatile int sys_tick = 0;

static void timer_handler(unsigned id)
{
    uint32_t period = arch_timer_frequecy()/2;

    arch_timer_compare(period);

    sys_tick++;
    INFO("%s: Processed on CPU[%d] count=0x%0x \n", __func__, get_cpuid(), arch_timer_count());

}

static int intr_demo_run(void)
{
    /* delay() */
    ndelay(50);
    udelay(50);
    mdelay(50);

    INFO("%s: CPU[%d] timer freq = %d\n", __func__, get_cpuid(), arch_timer_frequecy());

    arch_timer_interrupt_enable(false);     /* 先关闭arch timer中断 */
    arch_timer_enable(true);                /* 使能arch timer */
    arch_timer_compare(arch_timer_frequecy()/2);  /* 设置中断间隔为500ms */
    arch_timer_interrupt_enable(true);     /* 先关闭arch timer中断 */

    while(sys_tick < 5);

    arch_timer_interrupt_enable(false);     /* 结束后关闭arch timer中断 */

    /* 打印 */
    ASSERT_TRUE(true);

    return 0;
}

static void intr_demo_init(void)
{
    /*
     * 注册并使能中断。
     * @param1: 中断号, arch timer的virtual中断为27
     * @param2: 中断处理函数
     * 当前在哪个CPU上注册中断，就在哪个CPU上处理中断
     */
     request_irq(27, timer_handler);
}

static void intr_demo_exit(void)
{
    /* 注销中断 */
    free_irq(27);
}


DECLARE_TEST_CASE(          /* 声明了一个单元测例, 测试框架会依次调用下面的init(), run(), exit()函数 */
        interrupt_demo,     /* 测例名字，不用带引号"" */
        intr_demo_init,     /* 测例预初始化函数，若不需要可以为NULL. 比如可以把复位和时钟初始化放这里 */
        intr_demo_run,      /* 测例执行主体函数，必须定义 */
        intr_demo_exit      /* 测例退出函数，若不需要可以为NULL. 比如结束测例后需要关时钟 */
);
